
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template

import os,copy,logging

effects = (
     {'key':'invisibility',  'name':'Invisibility', 	'hasval':False,	'isbad':False,	'care':'d',	},
     {'key':'jump',          'name':'Jump', 			'hasval':False,	'isbad':False,	'care':'d',	},
     {'key':'nightVision',   'name':'Night Vision', 	'hasval':False,	'isbad':False,	'care':'d',	},
     {'key':'regeneration',  'name':'Regeneration',		'hasval':False,	'isbad':False,	'care':'d',	},
     {'key':'fireResistance','name':'Fire Resistance', 	'hasval':False,	'isbad':False,	'care':'d',	},
     {'key':'waterBreathing','name':'Water Breathing',	'hasval':False,	'isbad':False,	'care':'d',	},
     {'key':'damageBoost',   'name':'Damage Boost',		'hasval':True,	'isbad':False,	'care':'d',	},
     {'key':'digSpeed',      'name':'Dig Speed',		'hasval':True,	'isbad':False,	'care':'d',	},
     {'key':'heal',          'name':'Heal', 			'hasval':True,	'isbad':False,	'care':'0',	},
     {'key':'moveSpeed',     'name':'Move Speed', 		'hasval':True,	'isbad':False,	'care':'d',	},
     {'key':'resistance',    'name':'Resistance',		'hasval':True,	'isbad':False,	'care':'d',	},
     {'key':'hunger',        'name':'Hunger', 			'hasval':False,	'isbad':True,	'care':'d',	},
     {'key':'moveSlowdown',  'name':'Move Slowdown', 	'hasval':False,	'isbad':True,	'care':'d',	},
     {'key':'weakness'      ,'name':'Weakness',			'hasval':False,	'isbad':True,	'care':'d',	},
     {'key':'digSlowDown',   'name':'Dig Slow Down',	'hasval':False,	'isbad':True,	'care':'d',	},
     {'key':'blindness',     'name':'Blindness',		'hasval':False,	'isbad':True,	'care':'d',	},
     {'key':'confusion',     'name':'Confusion',		'hasval':False,	'isbad':True,	'care':'d',	},
     {'key':'harm',          'name':'Harm', 			'hasval':True,	'isbad':True,	'care':'n',	},
     {'key':'poison',        'name':'Poison',			'hasval':True,	'isbad':True,	'care':'d',	},
)
mapeffects = {}
for effect in effects:
	mapeffects[effect['key']] = effect


ingredients = (
	{'key':"Water",				'name':"Water",					'check':True,	},
	{'key':"Sugar",				'name':"Sugar",					'check':True,	},
	{'key':"GhastTear",			'name':"Ghast Tear",			'check':True,	},
	{'key':"SpiderEye",			'name':"Spider Eye",			'check':True,	},
	{'key':"FermentedSpiderEye",'name':"Fermented Spider Eye",	'check':True,	},
	{'key':"BlazePower",		'name':"Blaze Powder",			'check':True,	},
	{'key':"MagmaCream",		'name':"Magma Cream",			'check':True,	},
	{'key':"NetherWart", 		'name':"Nether Wart", 			'check':True,	},
)

effectmap = {
	'invisibility':'Invisibility', 	
	'jump':'Jump', 			
	'nightVision':'Night Vision', 	
	'regeneration':'Regeneration',		
	'fireResistance':'Fire Resistance', 	
	'waterBreathing':'Water Breathing',	
	'damageBoost':'Damage Boost',		
	'digSpeed':'Dig Speed',		
	'heal':'Heal', 			
	'moveSpeed':'Move Speed', 		
	'resistance':'Resistance',		
	'hunger':'Hunger', 			
	'moveSlowdown':'Move Slowdown', 	
	'weakness'      :'Weakness',			
	'digSlowDown':'Dig Slow Down',	
	'blindness':'Blindness',		
	'confusion':'Confusion',		
	'harm':'Harm', 			
	'poison':'Poison',			
}

alleffects = set(effectmap.keys()) 



ingmap = {
"Water"				:["Water",				"img/Grid_Water_Bucket.png",		],
"Sugar"				:["Sugar",				"img/Grid_Sugar.png",				],
"GhastTear"			:["Ghast Tear",			"img/Grid_Ghast_Tear.png",			],
"SpiderEye"			:["Spider Eye",			"img/Grid_Spider_Eye.png",			],
"FermentedSpiderEye":["Fermented Spider Eye","img/Grid_Fermented_Spider_Eye.png",],
"BlazePower"		:["Blaze Powder",		"img/Grid_Blaze_Powder.png",		],
"MagmaCream"		:["Magma Cream",		"img/Grid_Magma_Cream.png",			],
"NetherWart"		:["Nether Wart",		"img/Grid_Nether_Wart_Seeds.png", 	],
}


class Potion(db.Model):
	""" key name = value """ 
	invisibility	= db.IntegerProperty()
	jump			= db.IntegerProperty()
	nightVision		= db.IntegerProperty()
	regeneration	= db.IntegerProperty()
	fireResistance  = db.IntegerProperty()
	waterBreathing	= db.IntegerProperty()
	damageBoost		= db.IntegerProperty()
	digSpeed		= db.IntegerProperty()
	heal			= db.IntegerProperty()
	moveSpeed		= db.IntegerProperty()
	resistance		= db.IntegerProperty()
	hunger			= db.IntegerProperty()
	moveSlowdown	= db.IntegerProperty()
	weakness		= db.IntegerProperty()
	digSlowDown		= db.IntegerProperty()
	blindness		= db.IntegerProperty()
	confusion		= db.IntegerProperty()
	harm			= db.IntegerProperty()
	poison			= db.IntegerProperty()

	invisibilityD   = db.IntegerProperty()
	jumpD           = db.IntegerProperty()
	nightVisionD    = db.IntegerProperty()
	regenerationD   = db.IntegerProperty()
	fireResistanceD = db.IntegerProperty()
	waterBreathingD = db.IntegerProperty()
	damageBoostD    = db.IntegerProperty()
	digSpeedD       = db.IntegerProperty()
	healD           = db.IntegerProperty()
	moveSpeedD      = db.IntegerProperty()
	resistanceD     = db.IntegerProperty()
	hungerD         = db.IntegerProperty()
	moveSlowdownD   = db.IntegerProperty()
	weaknessD       = db.IntegerProperty()
	digSlowDownD    = db.IntegerProperty()
	blindnessD      = db.IntegerProperty()
	confusionD      = db.IntegerProperty()
	harmD           = db.IntegerProperty()
	poisonD         = db.IntegerProperty()

	bad             = db.IntegerProperty()

	def effects(self):
		global effectmap,mapeffects
		effs = []
		valmap = {0:" I",1:" II",2:" III"}
		for key,value in self.__dict__.items():
			name= key[1:]
			try:
				if value in valmap and mapeffects[name]['hasval']:
					val = valmap[value]
				else:
					val=""
			except:
				val = ""
			if name in effectmap and value>=0:
				eff = {}
				eff['name'] = effectmap[name]+val 
				D = self.__dict__["_"+name+"D"]/20
				eff['duration'] = str(D/60)+":"+str(D%60).zfill(2)
				effs.append(eff)
		return effs
				

class PotionFormula(db.Model):
	potion = db.ReferenceProperty(Potion)	
	value            = db.IntegerProperty()
	Water			 = db.BooleanProperty()
	Sugar			 = db.BooleanProperty()
	GhastTear		 = db.BooleanProperty()
	SpiderEye		 = db.BooleanProperty()
	FermentedSpiderEye = db.BooleanProperty()
	BlazePower		 = db.BooleanProperty()
	MagmaCream		 = db.BooleanProperty()
	NetherWart 		 = db.BooleanProperty()
	ingredients = db.StringListProperty()
class PotionPage(webapp.RequestHandler):
	def get(self):
		potion = []
		try:
			id = int(self.request.get('id'))
			p = Potion.get_by_id(id)
			id = p.key().id()
			if p:
				allforms = p.potionformula_set.fetch(10) 
				forms = []
				for form in allforms:
					forms.append(
					{"inglist": [ingmap[ing] for ing in form.ingredients],
					 "id"     : form.value })
				if forms:
					potion.append({"id":id,"effects":p.effects(),"formulas":forms})
		except:
			pass
		template_values = {
			'results':potion,
			'effects':effects,
			'ingredients':ingredients,
		}

		path = os.path.join(os.path.dirname(__file__), 'potion.html')
		self.response.out.write(template.render(path, template_values))
class FormulaPage(webapp.RequestHandler):
	def get(self):
		potion = []
		try:
			fid = int(self.request.get('id'))
			formulas = PotionFormula.all().filter("value = ",fid).fetch(20)

			if formulas:
				p = formulas[0].potion
				id = p.key().id()
				if p:
					forms = []

					for form in formulas:
						forms.append(
						{"inglist": [ingmap[ing] for ing in form.ingredients],
						 "id"     : form.value })
					if forms:
						potion.append({"id":id,"effects":p.effects(),"formulas":forms})
		except:
			pass
		template_values = {
			'results':potion,
			'effects':effects,
			'ingredients':ingredients,
		}

		path = os.path.join(os.path.dirname(__file__), 'potion.html')
		self.response.out.write(template.render(path, template_values))
class MainPage(webapp.RequestHandler):
	def get(self):
		template_values = {
			'effects':effects,
			'ingredients':ingredients,
			'url': 'http://www.minecraftwiki.net/wiki/Brewing',
			'url_linktext': 'More about Potions on the Minecraft.net wiki',
		}
		q = Potion.all().filter("heal =",0)

		template_values.update(self.get_result_of_query(q,set(ingmap.keys())))

		path = os.path.join(os.path.dirname(__file__), 'index.html')
		self.response.out.write(template.render(path, template_values))
	def post(self):
		q = Potion.all()
		seteffects = {}
		noteffects = set()
		listingred = []
		myeffects = copy.deepcopy(effects)
		myingredients = copy.deepcopy(ingredients)
		
		for effect in myeffects:
			care = self.request.get(effect['key'])
			effect["care"]=care
			if care=='y':
				seteffects[effect['key']]=0
			elif care=='n':
				noteffects.add(effect['key'])
			elif care in ('0','1','2'):
				seteffects[effect['key']]=int(care)

		for effect,value in seteffects.items():
			q.filter(effect+" =", value)
		for effect in noteffects:
			q.filter(effect+" =", -1)

		for ingred in myingredients:
			if self.request.get(ingred['key']):
				listingred.append(ingred['key'])
				ingred["check"]=True
			else:
				ingred["check"]=False
		setingreds = set(listingred)

		q.order("bad")
		template_values = {
			'effects':myeffects,
			'ingredients':myingredients,
			'url': 'http://www.minecraftwiki.net/wiki/Brewing',
			'url_linktext': 'More about Potions on the Minecraft.net wiki',
		}

		template_values.update(self.get_result_of_query(q,setingreds))

		path = os.path.join(os.path.dirname(__file__), 'index.html')
		self.response.out.write(template.render(path, template_values))
	def get_result_of_query(self,q,setingreds):
		potions = []
		count = 0
		psize = 100
		limit = False
		result = q.fetch(psize)
		for p in result:
			id = p.key().id()
			allforms = p.potionformula_set.fetch(10) #filter("ingredients IN",listingred).fetch(20)
			forms = []
			for form in allforms:
				if set(form.ingredients) - setingreds:
					continue
				forms.append(
				{"inglist": [ingmap[ing] for ing in form.ingredients],
				 "id"     : form.value })
			else:
				if forms:
					forms.sort(key=lambda x:len(x["inglist"]))
					count += 1
					potions.append(
							{"id":id,"effects":p.effects(),
								"formulas":forms})
			if count > 20:
				break
		else:
			limit = len(result) == psize
		potions.sort(key=lambda p:min(len(x["inglist"]) for x in p["formulas"]))

		return {'results':potions,'limit':limit}


application = webapp.WSGIApplication(
									 [
										 ('/', MainPage),
										 ('/potion', PotionPage),
										 ('/formula', FormulaPage),
									 ],
									 debug=True)

def main():
	run_wsgi_app(application)

if __name__ == "__main__":
	main()
